<template>
    <div class="upload-video">

        <!-- 上传进度 -->
        <!-- ,.MP4,.AVI,.RMVB,.MOV,.MPEG,.FLV,.WEBM -->
        <template v-if="!noUploadVideo">
            <el-progress v-if="uploadProgress" :percentage="uploadProgress"></el-progress>
            <el-upload
                v-else
                class="upload-btn"
                action="string"
                accept=".mp4,.avi,.rmvb,.mov,.mpeg,.flv,.webm"
                :show-file-list="false"
                :http-request="startUploadVideo">
                <el-button size="small" type="primary" style="width:100%">{{video ? noCover ? '点击上传视频' : '重新上传视频' : '点击上传视频'}}</el-button>
            </el-upload>
        </template>

        <!-- 获取封面 -->
        <template v-if="OSSVideoId && !noCover">
            <div
                v-if="coverLoading"
                class="cover-loading"
                v-loading="coverLoading"
                element-loading-text="拼命加载封面中"
                element-loading-spinner="el-icon-loading">
            </div>
            <el-button v-else size="small" type="primary" style="margin-top:10px;width:100%" @click="getCoverClick">选择封面</el-button>
        </template>

        <!-- 选择封面弹窗 -->
        <el-dialog
            title="选择封面"
            :visible.sync="showImgList"
            class="img-list-dialog"
            width="80%">
            <ul class="img-list">
                <li
                    v-for="(item, index) in imgList"
                    :key="index"
                    @click="currentImgIndex = index"
                    :class="{'current-img': index === currentImgIndex}">
                    <img :src="item" alt="">
                    <span class="current-img-icon"></span>
                </li>
            </ul>
            <span slot="footer" class="dialog-footer">
                <el-button @click="showImgList = false">取 消</el-button>
                <el-button type="primary" @click="checkImgCover">选 中</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
/**
 * @change (videoUrl, videoDuration, videoCover) 提供三个参数 视频地址 视频时长 视频封面
 */
export default {
    name: 'uploadVideo',
    data () {
        return {
            coverLoading: false, // 获取封面加载loading
            uploadProgress: 0, // 上传进度
            video: '', // 视频url
            duration: 0,
            showImgList: false, // 选择封面弹窗 开关
            imgList: [], // 封面列表
            currentImgIndex: 0, // 选中的封面
            isNeedChangeType: false, // 是否需要转码 需要true  不需要false
            OSSVideoId: '' // OSS videoID 标志可以从服务器获取封面
        }
    },
    props: ['url', 'storageid', 'noCover', 'noUploadVideo'],
    watch: {
        url (val) {
            this.video = val
        },
        storageid (val) {
            this.OSSVideoId = val
        }
    },
    created () {
        this.video = this.url
        this.OSSVideoId = this.storageid
    },
    methods: {
        // 本地上传视频到阿里云
        async startUploadVideo (file) {
            this.myUploadFile = file.file// 选取上传文件
            let url = URL.createObjectURL(file.file)
            let audioElement = new Audio(url)
            audioElement.addEventListener('loadedmetadata', () => {
                this.duration = parseInt(audioElement.duration)
            })
            this.getAuth(() => {
                this.getUpload()
                // 确定上传开始
                this.startSubmit()
            })
        },

        // 获取权限
        async getAuth (cb) {
            // 注意：此接口根据自己后台提供的获取凭证接口来
            let res = await this.$http.post('/video/getVodStsToken')
            if (res.code === '0') {
                this.secretToken = res.data.securityToken
                this.accessKeySecret = res.data.accessKeySecret
                this.accessKeyId = res.data.accessKeyId

                this.videoDomain = res.data.videoDomain
                this.cateId = res.data.cateId
                this.expiration = res.data.expiration
                this.templateGroupId = res.data.templateGroupId
                this.storageLocation = res.data.storageLocation
                cb && cb()
            } else {
                this.$message({
                    message: '获取上传认证失败,请重新上传获取！',
                    type: 'error'
                })
            }
        },

        // 创建上传实例  上传钩子
        getUpload () {
            // eslint-disable-next-line no-undef
            this.myUploader = new AliyunUpload.Vod({
                partSize: 1048576, // 分片大小默认1M
                parallel: 5, // 并行上传分片个数，默认5
                retryCount: 3, // 网络原因失败时，重新上传次数，默认为3
                retryDuration: 2, // 网络原因失败时，重新上传间隔时间，默认为2秒
                userId: '1303984639806000',
                // 文件上传失败
                'onUploadFailed': (uploadInfo, code, message) => {
                    this.$message({
                        message: '上传失败，请重新上传',
                        type: 'error'
                    })
                },
                // 文件上传完成
                'onUploadSucceed': (uploadInfo) => {
                    // 上传成功后保存视频地址
                    this.uploadProgress = 0
                    this.OSSVideoId = uploadInfo.videoId
                    this.coverLoading = true
                    // this.video = 'https://avideo.shike.com/' + uploadInfo.object
                    this.video = this.videoDomain + '/' + uploadInfo.object
                    this.$emit('change', this.video, this.duration, this.OSSVideoId)
                    // 不需要获取封面
                    if (this.noCover) return
                    this.getSeverCover()
                },
                // 文件上传进度
                'onUploadProgress': (uploadInfo, totalSize, loadedPercent) => {
                    this.uploadProgress = Math.ceil(loadedPercent * 100) || 1
                },
                // STS临时账号会过期，过期时触发函数
                'onUploadTokenExpired': () => {
                    this.myUploader.resumeUploadWithAuth(this.getAuth)
                },
                // 开始上传
                'onUploadstarted': (uploadInfo) => {
                    this.myUploader.setSTSToken(uploadInfo, this.accessKeyId, this.accessKeySecret, this.secretToken)
                }
            })
        },

        //  确定上传到OSS
        startSubmit () {
            // 判断是否需要转码
            let name = this.myUploadFile.name
            let endType = name.substring(name.lastIndexOf('.') + 1)
            endType = endType.toLowerCase()
            let targetType = ['flv', 'avi', 'webm']

            // 获取上传凭证传回成功后执行 确定上传
            let userData
            if (targetType.includes(endType)) {
                userData = '{"Vod":{"Title":"qugame-work-media-' + new Date().getTime() + '","CateId":"' + this.cateId + '","TemplateGroupId":"' + this.templateGroupId + '","StorageLocation":"' + this.storageLocation + '"}}'
            } else {
                userData = '{"Vod":{"Title":"qugame-work-media-' + new Date().getTime() + '","CateId":"' + this.cateId + '","StorageLocation":"' + this.storageLocation + '"}}'
            }
            // 点播上传。每次上传都是独立的OSS object，所以添加文件时，不需要设置OSS的属性
            this.myUploader.addFile(this.myUploadFile, null, null, null, userData)
            this.myUploader.startUpload()
        },

        // 通知服务器开始截图
        async getSeverCover () {
            let res = await this.$http.post('/video/submitSnapshotJob', {
                videoId: this.OSSVideoId
            })
            if (res.code === '0') {
                this.forGetCover()
            } else {
                this.$message({
                    type: 'error',
                    message: '网络繁忙，获取封面失败，请手动上传！'
                })
                this.coverLoading = false // 取消获取封面Loading
            }
        },

        // 获取封面
        forGetCover (id) {
            this.timerId = setInterval(async () => {
                this.getCover()
            }, 1000)
        },

        // 从服务器获取封面
        async getCover () {
            let params = {
                videoId: this.OSSVideoId
            }
            // 是否需要转码
            let name = this.video
            let endType = name.substring(name.lastIndexOf('.') + 1)
            endType = endType.toLowerCase()
            let targetType = ['flv', 'avi', 'webm']
            if (targetType.includes(endType)) {
                params.format = 'mp4'
            }

            let res = await this.$http.post('/video/getVideoInfo', params)
            if (res.code === '0') {
                this.imgList = res.data.snapshots || []
                if (res.data.success) {
                    clearInterval(this.timerId)
                    let cover = this.imgList.length ? this.imgList[0] : ''
                    this.$emit('change', this.video, this.duration, this.OSSVideoId, cover, res.data.size, res.data.mp4Url)
                    this.coverLoading = false // 取消获取封面Loading
                    this.showImgList = true // 选择封面
                }
            } else {
                clearInterval(this.timerId)
                this.coverLoading = false // 取消获取封面Loading
                this.$message({
                    type: 'error',
                    message: res.desc
                })
            }
        },

        // 手动获取封面
        getCoverClick () {
            if (this.imgList.length) {
                this.showImgList = true
            } else {
                this.coverLoading = true
                this.getSeverCover()
            }
        },

        // 选择封面
        checkImgCover (item) {
            let cover = this.imgList[this.currentImgIndex]
            this.$emit('change', this.video, this.duration, this.OSSVideoId, cover)
            this.showImgList = false
        }
    }
}
</script>

<style lang="scss" scoped>
    .upload-video {
        .upload-btn {
            width: 100%;
            margin-top: 10px;
            /deep/ .el-upload {
                width: 100%;
            }
        }

        .cover-loading {
            height: 50px;
        }
        .img-list-dialog {
            /deep/ .el-dialog__body {
                padding: 0 20px;
            }
            .img-list {
                display: -webkit-box;
                overflow-x: scroll;
                -webkit-overflow-scrolling:touch;
                > li {
                    position: relative;
                    width: 140px;
                    height: 200px;
                    background-color: #ccc;
                    margin-right: 10px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    > img {
                        width: 100%;
                        max-height: 100%;
                    }
                    .current-img-icon {
                        position: absolute;
                        top: 5px;
                        right: 5px;
                        z-index: 1;
                        opacity: 0;
                        background-image: url('./img/check-video-img.png');
                        background-size: 100% 100%;
                        width: 15px;
                        height: 15px;
                    }
                }
                .current-img {
                    border: 1px solid red;
                    .current-img-icon {
                        opacity: 1;
                    }
                }
            }
        }
    }
</style>
